/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is dual-licensed under either the MIT license found in the
 * LICENSE-MIT file in the root directory of this source tree or the Apache
 * License, Version 2.0 found in the LICENSE-APACHE file in the root directory
 * of this source tree. You may select, at your option, one of the
 * above-listed licenses.
 */

package main

import (
	"encoding/json"
	"log/slog"
	"os"
)

// BuckConfig option to generate BUCK files
type BuckConfig struct {
	Preambule             string `json:"preambule"`                // added to the top of each BUCK file, e.g. "# Generated by gobuckify"
	LoadGoBinaryRule      string `json:"load_go_binary_rule"`      // load statement for alternative go_binary rule
	LoadGoLibraryRule     string `json:"load_go_library_rule"`     // load statement for alternative go_library rule
	GoBinaryRule          string `json:"go_binary_rule"`           // alternaive name for go_binary rule. Default: "go_binary"
	GoLibraryRule         string `json:"go_library_rule"`          // alternaive name for go_library rule. Default: "go_library"
	DepsTargetLabelPrefix string `json:"deps_target_label_prefix"` // prefix for dependencies, if provided deps formatted as "{prefix}{import}:{import_suffix}"
	GenerateEmbedSrcs     bool   `json:"generate_embed_srcs"`      // generate srcs for go:embed directives (sadly not open-sourced yet)
	DepsAttr              string `json:"deps_attr"`                // custom attribute for dependencies e.g. "go_external_deps". Default: "deps"
}

// PlatformConfig mapping between goos/goarch and buck os/arch
type PlatformConfig struct {
	GoOS     string `json:"go_os"`
	GoArch   string `json:"go_arch"`
	BuckOS   string `json:"buck_os"`
	BuckArch string `json:"buck_arch"`
}

// Config is the configuration for buckify
type Config struct {
	Buck        BuckConfig       `json:"buck"`         // options for BUCK files
	Platforms   []PlatformConfig `json:"platforms"`    // list of platforms we query `go list`
	DefaultTags []string         `json:"default_tags"` // list of tags we allways pass to `go list`
}

// FromJSON reads a config from a JSON file
func FromJSON(filename string) (*Config, error) {
	var c Config
	data, err := os.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(data, &c)
	if err != nil {
		return nil, err
	}
	ensureDefaultValues(&c)
	return &c, nil
}

func ensureDefaultValues(c *Config) {
	if c.Buck.GoBinaryRule == "" {
		c.Buck.GoBinaryRule = "go_binary"
	}
	if c.Buck.GoLibraryRule == "" {
		c.Buck.GoLibraryRule = "go_library"
	}
	if c.Buck.DepsAttr == "" {
		c.Buck.DepsAttr = "deps"
	}
	if c.Buck.DepsTargetLabelPrefix == "" {
		slog.Info("buck.deps_target_label_prefix is not set, dependencies will be formatted as raw import paths")
	}
}
